package cn.edu.tju.cas.rest.controller;

import cn.edu.tju.cas.entity.GroupEntity;
import cn.edu.tju.cas.entity.SystemEntity;
import cn.edu.tju.cas.entity.UserEntity;
import cn.edu.tju.cas.entity.UserGroupApplyEntity;
import cn.edu.tju.cas.rest.aspect.RequiredAdmin;
import cn.edu.tju.cas.service.ApplyService;
import cn.edu.tju.cas.service.UserService;
import cn.edu.tju.cas.util.*;
import cn.edu.tju.cas.util.common.MyDate;

import cn.edu.tju.cas.util.StateCode;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jca.cci.core.InteractionCallback;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.swing.plaf.nimbus.State;
import java.io.IOException;
import java.net.URLDecoder;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
//import org.springframework

/**
 * Created by catold on 16/2/21.
 */
@Controller
@RequestMapping("user")
public class UserController {
    private static Logger logger = LoggerFactory.getLogger(UserController.class);


    @Autowired
    private UserService userService;

    @Autowired
    private ApplyService applyService;

    @Autowired
    private Config config;

    @RequiredAdmin
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public @ResponseBody Object get(@PathVariable("id") int id) {
        return userService.findById(id);
    }

    @RequestMapping(value = "/info", method = RequestMethod.GET)
    public @ResponseBody
    StateCode getUserInfo() {
        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);
        stateCode.addData("userInfo", SessionUtil.getUser());
        return stateCode;
    }

    /**
     * 根据身份证号
     * 获取用户已经通过认证的角色
     * @param idCard
     * @return
     */
    @RequestMapping(value = "/groups", method = RequestMethod.GET)
    public @ResponseBody StateCode getCertifiedGroup(@RequestParam (value = "idCard",required = true) String idCard){

        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);

        UserEntity user = userService.getUserIdByIdCard(idCard);
        logger.info("idCard" + idCard + "对应的用户是： "+user);
        System.out.println("idCard" + idCard + "对应的用户是： " + user);
        if(user != null){
            System.out.println("idCard" + idCard + "对应的用户是： " + user.getUsername());
            List<UserGroupApplyEntity> applys = applyService.getCertifiedUserGroupApply(user.getUserId());
            if(applys != null){
                List<GroupEntity> groups = new ArrayList<GroupEntity>();
                for(UserGroupApplyEntity item:applys){
                    groups.add(item.getGroupEntity());
                }
                stateCode.addData("roles", groups);
            }else{
                stateCode.addData("roles", null);
            }
        }
        return stateCode;
    }


    /**
     * 通过传入用户的身份证号码和认证角色id，获取用户的认证信息资料
     * @param idCard
     * @return
     */
    @RequestMapping(value = "/group/info", method = RequestMethod.GET)
    public @ResponseBody StateCode getCertificationInfo(@RequestParam (value = "idCard",required = true) String idCard,
                                                        @RequestParam (value = "groupId",required = true) int groupId){
        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);
        UserEntity user = userService.getUserIdByIdCard(idCard);
        if(user != null){
            stateCode.addData("certificationInfo",userService.getCertificationInfo(user.getUserId(),groupId));
        }

        return stateCode;
    }




    @RequiredAdmin
    @RequestMapping(value = "", method = RequestMethod.GET)
    public @ResponseBody
    StateCode getAllUser(@RequestParam(value = "isAdmin", required = false) Integer isAdmin) {
        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);
        if(isAdmin == null){
            stateCode.addData("users", userService.findAll());
        } else {
            stateCode.addData("users", userService.findByAdminType(isAdmin));
        }
        return stateCode;
    }

    /**
     * Spring MVＣ　绑定方式，传入参数　input username,password
     * 添加新用户 ( 角色，用户名，密码，身份证）
     * @param userEntity
     * @return
     */
    @RequiredAdmin
    @RequestMapping(value = "", method = RequestMethod.POST)
    public @ResponseBody
    StateCode addUser(@RequestBody UserEntity userEntity) {
        // 初始化 userEntity信息
        userEntity.setIsAdmin(0);
        // user 初始状态为 0：正常
        userEntity.setStatus(0);

        // 保存用户信息
        userService.save(userEntity);

        // 为用户添加角色
        Set<GroupEntity> groupEntities = userEntity.getGroupEntities();
        for(GroupEntity groupEntity:groupEntities){
            System.out.println("groupEntity is : "+ groupEntity.getGroupId() + "  " + groupEntity.getName());
            userService.addGroupToUser(userEntity.getUserId(), groupEntity.getGroupId());
        }




        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);
        stateCode.addData("result", Constants.ADD_RESULT_SUCCESS);
        return stateCode;
    }


    /**
     * 设置用户角色，设为 admin 或者 设置为 User
     * @param admin_code
     * @return
     */
    @RequiredAdmin
    @RequestMapping(value = "/{id}/admin/{admin_code}", method = RequestMethod.PUT)
    public @ResponseBody
    StateCode setAdmin(@PathVariable ("id") int id, @PathVariable("admin_code") int admin_code) {
        // 获取 user
        UserEntity userEntity = userService.findById(id);

        if(userEntity == null){
            // 暂时输出这个错
            return StateCode.buildCode(BizCode.SUCCESS);
        }
        // 设置用户角色
        userEntity.setIsAdmin(admin_code);

        userService.update(userEntity);
        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);
        stateCode.addData("result", Constants.UPDATE_RESULT_SUCCESS);
        return stateCode;
    }


    /**
     * 传入参数　input username,password
     * 修改用户信息
     * @return
     */
    @RequiredAdmin
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public @ResponseBody
    StateCode updateUser(@PathVariable("id") int id, @RequestBody UserEntity userEntityNew) {

        UserEntity userEntity = userService.findById(id);
        userEntity.setPassword(userEntityNew.getPassword());
        userEntity.setIdCard(userEntityNew.getIdCard());
        userService.update(userEntity);

        // 获取用户旧的角色（包括已通过和未通过和正在审查）
        List<UserGroupApplyEntity> groupApplies = applyService.getUserGroupApply(id);

        // 为用户修改角色
        // 1、删除用户所有旧角色
        applyService.removeAllRolesByUserId(id);

        // 2、为用户重新赋予新角色
        Set<GroupEntity> groupEntities = userEntityNew.getGroupEntities();
        if(groupEntities!=null && groupEntities.size() > 0){
            for(GroupEntity groupEntity:groupEntities){
                System.out.println("groupEntity is : "+ groupEntity.getGroupId() + "  " + groupEntity.getName());
                userService.addGroupToUser(userEntity.getUserId(), groupEntity.getGroupId());
            }
        }
        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);
        stateCode.addData("result", Constants.UPDATE_RESULT_SUCCESS);
        return stateCode;
    }

    private boolean hasRole(List<UserGroupApplyEntity> roles,GroupEntity newRole){
        for(UserGroupApplyEntity apply:roles){
            if(apply.getGroupEntity().getGroupId() == newRole.getGroupId()){
                return true;
            }
        }
        return false;
    }

    /**
     * 获取用户申请的所有 角色
     * @return
     */
    @RequestMapping(value = "/group", method = RequestMethod.GET)
    public @ResponseBody StateCode getGroupHistory() {

        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);
        int userId = SessionUtil.getUser().getUserId();
        stateCode.addData("groups", applyService.getUserGroupApply(userId));
        return stateCode;
    }

    /**
     * 为用户添加角色
     * @return
     */
    @RequiredAdmin
    @RequestMapping(value = "/{id}/group/{groupId}", method = RequestMethod.POST)
    public @ResponseBody StateCode addGroupToUser(@PathVariable("id") int id, @PathVariable("groupId") int groupId) {
        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);

        if (!userService.addGroupToUser(id, groupId)) {
            StateCode.buildCode(BizCode.ADD_GROUP_TO_USER_WRONG);
        }
        return stateCode;
    }

    /**
     * 登出
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public void logout(HttpServletResponse response) throws IOException {
        SessionUtil.clear();
        response.sendRedirect(config.getCasLogoutUrl());
    }


    /**
     * 登出
     */
    @RequestMapping(value = "/logout", method = RequestMethod.POST)
    public void logoutPost(@RequestBody String content, @RequestParam("logoutRequest") String request) throws IOException {
//        SessionUtil.clear();
        System.out.println(request);
        String sessionIndex = XmlDealer.getSessionIdFromLogout(request);
        if (sessionIndex.isEmpty()) {
            return;
        }

        PassedTicket.getInstance().removeTicket(sessionIndex);
    }




    /**
     * 与单点登录系统对接登录接口
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public @ResponseBody void login(@RequestParam(value = "ticket", required = false) String ticket, HttpServletResponse response) throws Exception {
        StateCode stateCode = new StateCode();
        if (ticket == null || "".equals(ticket)) {
            // ticket为空
            stateCode = StateCode.buildCode(BizCode.TICKET_WRONG);
        } else {
            // 验证服务正确性
            CloseableHttpClient httpclient = HttpClients.createDefault();
            try {
                HttpGet httpget = new HttpGet(config.getCasLoginValidate() + ticket);

                System.out.println("Executing request " + httpget.getRequestLine());

                // Create a custom response handler
                ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                    @Override
                    public String handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
                        int status = httpResponse.getStatusLine().getStatusCode();
                        if (status >= 200 && status < 300) {
                            HttpEntity entity = httpResponse.getEntity();
                            return entity != null ? EntityUtils.toString(entity) : null;
                        } else {
                            throw new ClientProtocolException("Unexpected response status: " + status);
                        }
                    }
                };
                String responseBody = httpclient.execute(httpget, responseHandler);
                System.out.println("----------------------------------------");
                System.out.println(responseBody);

                UserEntity userEntity = XmlDealer.getFromXml(responseBody);
                if(userEntity == null){
                    stateCode = StateCode.buildCode(BizCode.TICKET_WRONG);
                } else {
                    SessionUtil.setUser(userService.findByUsername(userEntity.getUsername()));
                    SessionUtil.setLogin(true);
                }
            } catch (Exception e) {
                stateCode = StateCode.buildCode(BizCode.TICKET_WRONG);
            } finally {
                httpclient.close();
            }
        }
        SessionUtil.setTicket(ticket);
        PassedTicket.getInstance().addTicket(ticket);
        response.sendRedirect("/server/index.html");
    }

    /**
     * 是否登录接口
     * @return
     */
    @RequestMapping(value = "/loginstatus", method = RequestMethod.GET)
    public @ResponseBody Object loginCheck() {
        StateCode stateCode = StateCode.buildCode(BizCode.SUCCESS);

        stateCode.addData("loginstatus", SessionUtil.isLogin());
        return stateCode;
    }
}
